﻿#ifndef FTPDOWNLOADER_H
#define FTPDOWNLOADER_H

#include "Downloader.h"
#include <string>
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDataStream>
#include <QFile>
#include <QThread>
#include <QTimer>
#include <QMutex>
#include <mutex>
#include <QWaitCondition>
#include <condition_variable>
const int PORT = 21;
const int BUFLEN = 4096;
const int DATABUFLEN = 4096;
const char* const DELIMITER = "\r\n";

class FtpDownloader : public QObject
{
    Q_OBJECT
public:
    enum DownloadStatus
    {
        t_Start,                // 起始状态
        t_Downloading,          // 下载中
        t_Pause,                // 暂停
        t_Finished,             // 下载完成
        t_Error                 // 错误
    };
    const int PORT = 21;
    const int BUFLEN = 4096;
    const int DATABUFLEN = 4096;
    const char* const DELIMITER = "\r\n";
    QWaitCondition m_condition; // 互斥条件，用于暂停线程
    QMutex         m_mutex;     // 互斥锁，互斥条件用
    std::string m_outputFile = "C:\\Users\\CHD\\Desktop\\download.txt";

    std::atomic_bool isStop;
    public:
    QNetworkAccessManager *m_Qnam;
    QNetworkReply         *m_Reply;
    QFile                 *m_File;
    QTimer                *m_pTimer;        //用于限速的定时器
    QTcpSocket            *m_commandSocket;//Ftp交互Socket
    QTcpSocket            *m_dataSocket;   //Ftp数据Socket

    int       m_Index;              // 下载器编号，控制器用于区分不同线程的下载器
    QUrl      m_Url;                // URL地址
    int       m_speed;              // 最高下载速度
    qint64    m_CurrentRecvBytes;   // 已下载字节数（用于定时器限速）
    qint64    m_HaveDoneBytes;      // 已下载字节数
    qint64    m_StartPoint;         // 下载文件的开始字节
    qint64    m_EndPoint;           // 下载文件的结束字节

    DownloadStatus  m_status = t_Start;
private:
    // 用于socket首发
    std::string     recvInfo;
    std::string     nextInfo;
    char* buf     = new char[BUFLEN];  //缓冲区
    char* databuf = new char[DATABUFLEN];//数据缓冲区
    std::string     m_userName;  //用户账号
    std::string     m_password;  //用户密码
    int             dataPort;    //流入模式下的动态端口
    bool            isDone;
    //const int       m_Index;
public:
    FtpDownloader(int startPoint, int endPoint, int index, int speed, QObject* parent = nullptr);
    ~FtpDownloader();

    // 开始下载
     void startDownload(QUrl url) ;
    // 获取当前下载进度
     void getCurrentDownProgress(int& currentSize, int& totalSize) ;
    // 获取当前状态
     DownloadStatus getCurrentStatus(void) ;
    void saveDownload(int line_to_edit,std::string new_star,std::int64_t countSize);
private:
    // Socket通讯工具方法
    int excuteCmd(std::string cmd);
    int recvControl(int stateCode, std::string errorInfo="0");
    //检测被动模式下状态码
    int getStateCode();
    //被动模式下的端口号格式
    int getPortNum();
    //被动模式
    int intoPasv();
// 信号与槽函数
public:  signals:
         void DownloadFinished(int);
         void error(QString errorString);
         void downFinished(void);
         //每读取一次就传给Download控制器
         void updateCurrentSize(int,int);
public slots:
    //Downloader传来的开始
     void onStart(QUrl url, QFile* filePath);
    //Downloader传来的停止
     void onStop() ;
    //Downloader传来的恢复
     void onRestart() ;
    //Downloader传来的删除
    void onDelete();
    // Ftp被动模式下 检测数据Socket是否断开，断开则重连
    void onControlReadyRead();
    //写入数据
     void onReplyReadyRead() ;
    //写入数据完成
     void onReplyFinished() ;
    //定时唤醒(用于限速)
     void onTimeout() ;
};

#endif // FTPDOWNLOADER_H
